using System;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Xml;

namespace PropertyExpression.ControllableQuery.Toolkit
{
    public static class Util
    {
        public static bool IsGenericTypeAndEquals(this Type type1, Type type2)
        {
            return type1.IsGenericType && type2.Equals(type1.GetGenericTypeDefinition());
        }

        public static MethodInfo GetMethodInfo<T>(Expression<T> expression)
        {
            return ((MethodCallExpression)expression.Body).Method;
        }

        public static bool GetAllowDbNull(this DataRow dataRow)
        {
            return (bool)dataRow["AllowDBNull"];
        }

        public static int GetColumnSize(this DataRow dataRow)
        {
            return (int)dataRow["ColumnSize"];
        }

        public static short GetNumericPrecision(this DataRow dataRow)
        {
            return (short)dataRow["NumericPrecision"];
        }

        public static short GetNumericScale(this DataRow dataRow)
        {
            return (short)dataRow["NumericScale"];
        }

        public static Type GetDataType(this DataRow dataRow)
        {
            return (Type)dataRow["DataType"];
        }

        public static string GetColumnName(this DataRow dataRow)
        {
            return (string)dataRow["ColumnName"];
        }

        public static string GetDataTypeName(this DataRow dataRow)
        {
            return (string)dataRow["DataTypeName"];
        }

        public static bool CompareSqlTypes(this string sqlType1, string sqlType2)
        {
            return String.Compare(sqlType1, sqlType2, true) == 0;
        }

        public static string GetParamAttributeValue(this ParamInfo paramInfo, XmlDocument xmlDocument, XmlNamespaceManager xmlNamespaceManager, string attributeName)
        {
            return xmlDocument.SelectNodes(
                String.Format(
                    @"//a:ColumnReference[@Column='{0}']/ancestor::a:Convert/@{1}",
                    paramInfo.Name, attributeName),
                xmlNamespaceManager).Cast<XmlNode>().Select(_ => _.InnerText).Distinct().Single();
        }

        public static int GetNVarCharLength(this SqlParamInfo sqlParamInfo, XmlDocument xmlDocument, XmlNamespaceManager xmlNamespaceManager)
        {
            return int.Parse(sqlParamInfo.ParamInfo.GetParamAttributeValue(xmlDocument, xmlNamespaceManager, "Length"))/2;
        }

        public static int GetPrecision(this SqlParamInfo sqlParamInfo, XmlDocument xmlDocument, XmlNamespaceManager xmlNamespaceManager)
        {
            return int.Parse(sqlParamInfo.ParamInfo.GetParamAttributeValue(xmlDocument, xmlNamespaceManager, "Precision"));
        }

        public static int GetScale(this SqlParamInfo sqlParamInfo, XmlDocument xmlDocument, XmlNamespaceManager xmlNamespaceManager)
        {
            return int.Parse(sqlParamInfo.ParamInfo.GetParamAttributeValue(xmlDocument, xmlNamespaceManager, "Scale"));
        }
    }
}